﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ufida.u9.ait.openapi.utils;
using UFIDA.U9.AR.Receival;
using UFIDA.U9.AR.Receival.Exceptions;
using UFIDA.U9.Base;
using UFIDA.U9.Base.Currency;
using UFIDA.U9.Base.Doc;
using UFIDA.U9.CBO.FI.BankAccount;
using UFIDA.U9.CBO.FI.Enums;
using UFIDA.U9.CBO.FI.IncExpItem;
using UFIDA.U9.CBO.FI.SettlementMethod;
using UFIDA.U9.CBO.FI.Tax;
using UFIDA.U9.CBO.HR.Department;
using UFIDA.U9.CBO.HR.Operator;
using UFIDA.U9.CBO.SCM.Customer;
using UFIDA.U9.CBO.SCM.ProjectTask;
using UFIDA.U9.CBO.SCM.Supplier;
using UFSoft.UBF.Business;
using UFSoft.UBF.Eventing;
using UFSoft.UBF.Execution.WorkManagers;
using ServiceOrderSubscriber = UFIDA.U9.AR.Receival.ServiceOrderSubscriber;

namespace ufida.u9.ait.openapi
{
    internal class RecBillBase
    {
        public static RecBillHead ApproveDoc(RecBillHead doc)
        {
            if (doc.DocStatus == BillStatusEnum.Approved) 
                throw new Exception($"单号:[{doc.DocNo}]状态已审,不能重复审批");


            //RecBillApprovingBP bp = new RecBillApprovingBP();
            //bp.RecBillHead = doc.Key;
            //bp.CurrentSysVersion = doc.SysVersion;
            //bp.Do();

            doc = doc.Key.GetEntity();
            if (doc.IsBlankOut())
            {
                throw new CanApprovedForCancelBillException();
            }

            using (ISession session = Session.Open())
            {
                doc.DoApproving();
                session.Commit();
            }

            if (doc.DocumentType.ConfirmType.Equals(ConfirmTypeEnum.ApproveFlow))
            {
                throw new Exception("确认方式为审批流程,不能自动审核");
                //ServiceOrderSubscriber serviceOrderSubscriber = new ServiceOrderSubscriber();
                //serviceOrderSubscriber.EntityKey = doc.Key;
                //EventHelper.SubscribeApprovalResultEvent(doc.Key, (IEventSubscriber)serviceOrderSubscriber);
                //ApprovalService.Instance.SubmitApproval(doc);
            }

            return doc;
        }
        public static RecBillHead UnApproveDoc(RecBillHead doc)
        {
            if (doc.DocStatus != BillStatusEnum.Approved)
                throw new Exception($"单号:[{doc.DocNo}]状态不为已审");

            doc = doc.Key.GetEntity();
            RecBillCancelApprovedBP bp = new RecBillCancelApprovedBP();
            bp.RecBillHead = doc.Key;
            bp.CurrentSysVersion = doc.SysVersion;
            bp.Do();

            return doc;
        }

        public static RecBillHead CreateDoc(RecBillHeadAITDTOData dto)
        {
            RecBillHead doc = null;
            using (ISession session = Session.Open())
            {
                doc = RecBillHead.Create();
                CreateHead(doc, dto);
                CreateLines(doc, dto);

                session.Commit();
            }
            return doc;
        }

        private static void CreateLines(RecBillHead doc, RecBillHeadAITDTOData dto)
        {
            if (dto.RecBillLines == null || dto.RecBillLines.Count <= 0) throw new Exception("RecBillLines必填");
            int rowno = 0;
            foreach (var linedto in dto.RecBillLines)
            {
                rowno += 10;
                RecBillLine line = RecBillLine.Create(doc);
                if (linedto.LineNum <= 0)
                {
                    line.LineNum = rowno;
                }
                else
                {
                    line.LineNum = rowno;
                }

                //税组合
                if (linedto.TaxSchedule != null)
                {
                    //优先 取行传入
                    line.TaxSchedule = EntityUtils.GetEntityByCode<TaxSchedule>(linedto.TaxSchedule.Code);
                }
                else if (doc.TaxSchedule != null)
                {
                    //其次 取头传入
                    line.TaxSchedule = doc.TaxSchedule;
                }
                line.TaxRate = 0;
                if (line.TaxSchedule != null)
                {
                    line.TaxRate = line.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;//税率
                }

                //金额
                //含税金额
                line.Money = new UFIDA.U9.CBO.FI.PropertyTypes.FAMoney()
                {
                    OCMoney = linedto.Money,
                    FCMoney = linedto.Money,
                };
                line.TotalMoney = line.Money;
                line.TotalBalance = line.Money;
                line.RecACCMoney = line.Money;
                //不含税金额
                decimal nonTax = linedto.Money / (1 + line.TaxRate);//不含税金额
                nonTax = U9Utils.GetRoundMoney(doc.RC, nonTax);
                line.NonTaxMoney = new UFIDA.U9.CBO.FI.PropertyTypes.FAMoney()
                {
                    OCMoney = nonTax,
                    FCMoney = nonTax,
                };
                //税额
                decimal tax = linedto.Money - nonTax;
                line.TaxMoney = new UFIDA.U9.CBO.FI.PropertyTypes.FAMoney()
                {
                    OCMoney = tax,
                    FCMoney = tax,
                };

                //扩展字段处理
                if (linedto.DescFlexField != null)
                {
                    line.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                    DTOUtils.DTOPropCopy(linedto.DescFlexField, line.DescFlexField);
                }

                //其它
                line.SignDate = doc.RecDate;//签发日期
                if(!string.IsNullOrEmpty(linedto.Maturity))
                    line.Maturity = DateTime.Parse(linedto.Maturity);//到期日
                //结算方式
                if (linedto.SettlementMethod == null) throw new Exception("SettlementMethod必填");
                line.SettlementMethod = EntityUtils.GetEntityByCode<SettlementMethod>(linedto.SettlementMethod.Code);
                line.SettlementMethodClass = line.SettlementMethod.SettlementClass;
                //收支项目
                line.IncomeExpendItem = EntityUtils.GetEntityByCode<IncExpItem>(linedto.IncomeExpendItem);
                //银行账号
                line.RecBkAccount = EntityUtils.GetEntityByCode<BankAccount>(linedto.RecBkAccount);
                if(line.RecBkAccount != null)
                {
                    line.RecBkAccName = line.RecBkAccount.Name;
                    line.RecBk = line.RecBkAccount.Bank;
                    line.RecBAC = doc.RC;//账号币种
                }

                line.RecBACToFCExRate = 1;
                line.RCToRecBACExRate = 1;
                line.RCToFCExRate = 1;
                //出票对象类型 依据收款对象
                line.RemitObjType = RemitObjTypeEnum.GetFromValue(dto.RecObjType);

                //创建用途子行
                RecBillUseLine line1 = RecBillUseLine.Create(line);
                line1.RecBillHead = doc;
                line1.RecProperty = RecPropertyEnum.GetFromValue(linedto.RecProperty);//用途
                line1.Transactor = doc.Transactor;
                line1.Receiver = doc.Receiver;
                //金额
                line1.Money = line.Money;
                line1.TotalMoney = line.Money;
                line1.RecACTotalMoney = linedto.Money;
                line1.RecACTotalBalance = linedto.Money;
                line1.NonTaxMoney = line.NonTaxMoney;
                line1.TaxMoney = line.TaxMoney;

                line1.CustSite = doc.CustSite;
                line1.Cust = doc.Cust;
                line1.Supp = doc.Supp;
                line1.SuppSite = doc.SuppSite;

                line1.SrcBillOrg = doc.SrcBillOrg;
                line1.LineNum = 10;
                //line1.IncomeExpendItem = line.IncomeExpendItem;
                line1.Dept = doc.Dept;
                line1.BizOrg = doc.BizOrg;
                if(!string.IsNullOrEmpty(linedto.EffectiveDate))
                    line1.EffectiveDate = DateTime.Parse(linedto.EffectiveDate);//到期日
                line1.IsOccupyCredit = true;
                line1.CCObjSite = doc.CCObjSite;
            }
        }

        private static void CreateHead(RecBillHead doc, RecBillHeadAITDTOData dto)
        {
            //doc.DocNo = dto.DocNo;
            if (String.IsNullOrEmpty(dto.RecDate)) throw new Exception("RecDate必填");
            doc.RecDate = DateTime.Parse(dto.RecDate);//收款日期
            doc.PostPeriod = EntityUtils.getPostPeriod(doc.RecDate);//记账期间
            if (string.IsNullOrEmpty(dto.DocumentType?.Code)) throw new Exception("DocumentType为空");
            doc.DocumentType = EntityUtils.GetEntityByCode<RecDocType>(dto.DocumentType);//单据类型
            //组织
            doc.Org = Context.LoginOrg;
            doc.SrcBillOrg = doc.Org;
            doc.SettleOrg = doc.Org;
            doc.BizOrg = doc.Org;
            //依据收款对象类型判断
            if (dto.RecObjType == 0)
            {
                //客户
                if (dto.Cust == null) throw new Exception("Cust必填");
                Customer cust = EntityUtils.GetEntityByCode<Customer>(dto.Cust.Code);
                doc.Cust = new CustomerMISCInfo()
                {
                    Customer = cust,
                    Name = cust.Name,
                    Code = cust.Code,
                };
                if (cust.CustomerSites != null && cust.CustomerSites.Count > 0)
                {
                    CustomerSite site = cust.CustomerSites[0];
                    doc.CustSite = new CustomerSiteMISCInfo()
                    {
                        CustomerSite = site,
                        Name = site.Name,
                        Code = site.Code,
                    };
                    doc.CCObjSite = site;
                };
            }else if( dto.RecObjType == 1)
            {
                //供应商
                if (dto.Supp == null) throw new Exception("Supp必填");
                Supplier supp=EntityUtils.GetEntityByCode<Supplier>(dto.Supp.Code);
                doc.Supp = new SupplierMISCInfo()
                {
                    Supplier = supp,
                    Name = supp.Name,
                    Code = supp.Code,
                };
                if(supp.SupplierSites!=null&& supp.SupplierSites.Count > 0)
                {
                    SupplierSite site = supp.SupplierSites[0];
                    doc.SuppSite = new SupplierSiteMISCInfo()
                    {
                        SupplierSite = site,
                        Name = site.Name,
                        Code = site.Code,
                    };
                }

            }
            else
            {
                throw new Exception("RecObjType只能是0或1");
            }
            doc.RecObjType = RecPayObjectTypeEnum.GetFromValue(dto.RecObjType);


            //扩展字段处理
            if (dto.DescFlexField != null)
            {
                doc.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto.DescFlexField, doc.DescFlexField);
            }
            //其它
            doc.TaxSchedule = EntityUtils.GetEntityByCode<TaxSchedule>(dto.TaxSchedule);//税组合
            doc.Note = dto.Note;//备注
            doc.RC = EntityUtils.GetEntityByCode<Currency>("C001");
            doc.FC = doc.RC;
            doc.AC = doc.RC;
            doc.Transactor = EntityUtils.GetEntityByCode<Operators>(dto.Transactor); //业务员
            doc.Receiver= EntityUtils.GetEntityByCode<Operators>(dto.Receiver); //收款员
            doc.Dept = EntityUtils.GetEntityByCode<Department>(dto.Dept);//部门
            doc.Project = EntityUtils.GetEntityByCode<Project>(dto.Project);//项目
            doc.RCToFCExRate = 1;
            doc.RCToACExRate = 1;
        }
    }
}
